﻿using Autofac;
using Fasterflect;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyModel;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.Loader;
using Loong.Dependency;

namespace Loong.Modules
{
    public class ModuleManager
    {
        private readonly List<ILoongModule> _modules;
        private bool _isLoaded = false;

        public ModuleManager()
        {
            _modules = new List<ILoongModule>();
        }

        public void ConfigureServices(IServiceCollection services, IConfiguration configuration)
        {
            if (!_isLoaded)
            {
                Load();
            }

            foreach (var module in _modules)
            {
                module.ConfigureServices(services, configuration);
            }
        }

        public void ConfigureContainer(ContainerBuilder builder)
        {
            if (!_isLoaded)
            {
                Load();
            }

            foreach (var module in _modules)
            {
                builder.RegisterModule(module);
            }
        }

        private void Load()
        {
            var libs = DependencyContext.Default.CompileLibraries.Where(lib => !lib.Serviceable && lib.Type == "project");
            foreach (var lib in libs)
            {
                var assembly = AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(lib.Name));
                var moduleTypes = assembly.GetTypes().Where(type => !type.IsInterface && typeof(ILoongModule).IsAssignableFrom(type));
                foreach (var moduleType in moduleTypes)
                {
                    var module = moduleType.CreateInstance() as ILoongModule;
                    _modules.Add(module);
                }
            }

            _isLoaded = true;
        }

        public void Initialize(ILifetimeScope lifetimeScope)
        {
            IocManager.IocContainer = lifetimeScope;

            foreach (var module in _modules)
            {
                module.Initialize();
            }
        }

        public void Shutdown()
        {
            foreach (var module in _modules)
            {
                module.Shutdown();
            }
        }
    }
}
